package com.lin.eventbus;

import com.lin.eventbus.internal.InternalInternalEventBus;
import com.lin.eventbus.callback.CallbackEvent;
import com.lin.eventbus.callback.CallbackFuture;
import com.lin.eventbus.function.LCallback;
import org.jetbrains.annotations.NotNull;

final public class EventBus {

    public static void register(@NotNull String channel, int ringBufferSize, int workerHandlers) {
        InternalInternalEventBus.INSTANCE.register(channel, ringBufferSize, workerHandlers);
    }

    public static void unregister(@NotNull String channel) {
        InternalInternalEventBus.INSTANCE.unregister(channel);
    }

    public static void subscribe(@NotNull IEventListener listener) {
        InternalInternalEventBus.INSTANCE.subscribe(listener);
    }

    public static void subscribe(@NotNull String channel, @NotNull IEventListener listener) {
        InternalInternalEventBus.INSTANCE.subscribe(channel, listener);
    }

    public static void unsubscribe(@NotNull IEventListener listener) {
        InternalInternalEventBus.INSTANCE.unsubscribe(listener);
    }

    public static void unsubscribe(@NotNull String channel, @NotNull IEventListener listener) {
        InternalInternalEventBus.INSTANCE.unsubscribe(channel, listener);
    }

    @NotNull
    public static EventFuture publish(@NotNull Event event) {
        return InternalInternalEventBus.INSTANCE.publish(event);
    }

    @NotNull
    public static EventFuture publish(@NotNull String channel, @NotNull Event event) {
        return InternalInternalEventBus.INSTANCE.publish(channel, event);
    }

    @NotNull
    public static <E> CallbackFuture<E> execute(@NotNull LCallback<E> callback) {
        CallbackFuture<E> future = new CallbackFuture<>();
        InternalInternalEventBus.INSTANCE.publish(new CallbackEvent(callback)).addListener(it -> {
            EventContext context;
            try {
                context = it.getUninterruptibly();
            } catch (Throwable ex) {
                future.complete(null, ex);
                return;
            }
            @SuppressWarnings("unchecked") E result = (E) context.getExtension("Callback.Result");
            future.complete(result);
        });
        return future;
    }

}
